/*
 * File:   Shell.cpp
 * Author: henrya
 *
 * Created on June 13, 2009, 6:58 PM
 */


#include "Shell.h"
#include "RuntimeException.h"
#include "ThreadCreationException.h"
#include "Tokenizer.h"
#include "IOException.h"
#include "Node.h"
#include "Network.h"

#include <iostream>
using std::cout;
using std::ifstream;
using std::endl;
using std::cin;

Shell::Shell() : interupted(false) {
}

Shell::~Shell() {
}

void* Shell::run(void* args) {
    Shell* thisShell = (Shell*) args;
    while (!thisShell->interupted) {
        cout << "> ";
        string in;
        getline(cin, in);
        if ("" == in)
            continue;
        Tokenizer tknzr(in);
        string command = *tknzr.next();
        if (command == "q") {
            thisShell->interrupt();
        } else {
            if (command == "CreateNet") {
                thisShell->mailer=thisShell->doCreateNet(tknzr.next());
            }
            else {
                if ("printRTs" == command){
                    thisShell->mailer->printRTs();
                }
            }
        }
    }
    pthread_exit(NULL);
}

void Shell::interrupt() {
    interupted = true;
}

void Shell::join() {
    if (pthread_join(self, NULL) != 0) {
        RuntimeException ex("Unable to join thread " + self);
        throw ex;
    }
}

Mailer* Shell::doCreateNet(string* filename) {
    if (filename == NULL) {
        cout << "Usage: CreateNet <config_file_name>" << endl;
        return NULL;
    }
    ifstream netConfStream((*filename).c_str(), ios::in);
    if (netConfStream == NULL) {
        IOException ex("Unable to open file: " + *filename);
        netConfStream.close();
        throw ex;
    }
    string mailerInboxSizeString;
    if (getline(netConfStream, mailerInboxSizeString) == 0) {
        RuntimeException ex("Network: Unexpected end of file or file format.");
        netConfStream.close();
        throw ex;
    }
    Tokenizer toknzr(mailerInboxSizeString);
    if (toknzr.peek() == NULL) {
        RuntimeException ex("Got NULL string while parsing mailbox size.");
        netConfStream.close();
        throw ex;
    }
    int mailerInboxSize = atoi((*toknzr.next()).c_str());
    if(mailerInboxSize<=0){
        cout<<"Given mailer inbox size in configuratrion file has to be > 0! Ignoring..."<<endl;
        netConfStream.close();
        return NULL;
    }
    Network* net = Network::createNetwork(netConfStream);
    Mailer* res=new Mailer(mailerInboxSize,net);
    netConfStream.close();
    return res;
}

void Shell::start() {
    if (pthread_create(&self, NULL, &Shell::run, (void*) this) != 0) {
        ThreadCreationException ex("Failed to create Shell thread");
        throw ex;
    }
}
